package com.iot.mqtt;

import com.iot.core.JsonHelper;
import com.iot.pojo.*;
import com.iot.service.Tdecive_handleService;
import com.iot.util.ApplicationContextHelper;
import com.iot.util.Common;
import com.iot.util.YT;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;

import java.util.Date;


/**
 * 发布消息的回调类
 * <p>
 * 必须实现MqttCallback的接口并实现对应的相关接口方法CallBack 类将实现 MqttCallBack。
 * 每个客户机标识都需要一个回调实例。在此示例中，构造函数传递客户机标识以另存为实例数据。
 * 在回调中，将它用来标识已经启动了该回调的哪个实例。
 * 必须在回调类中实现三个方法：
 * <p>
 * public void messageArrived(MqttTopic topic, MqttMessage message)接收已经预订的发布。
 * <p>
 * public void connectionLost(Throwable cause)在断开连接时调用。
 * <p>
 * public void deliveryComplete(MqttDeliveryToken token))
 * 接收到已经发布的 QoS 1 或 QoS 2 消息的传递令牌时调用。
 * 由 MqttClient.connect 激活此回调。
 */
public class ClientCallback implements MqttCallback {

    Tdecive_handleService service = ApplicationContextHelper.getBean(Tdecive_handleService.class);
    private Client client;

    public ClientCallback(Client client) {

        this.client = client;
    }

    public void connectionLost(Throwable cause) {
        while (!client.client.isConnected()) {
            try {
                System.out.println("client连接断开，可以做重连 " + Common.getNowTime());
                Thread.sleep(1000);
                client.start();
                System.out.println("client连接断开，重连完成 " + Common.getNowTime());
                break;
                //client.connect(options);
                //client.subscribe(topicFilters, qos);

            } catch (Exception e) {
                e.printStackTrace();
            }
//            try {
//                Thread.sleep(1000);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
        }
        // 连接丢失后，一般在这里面进行重连
        // System.out.println("连接断开，可以做重连");
    }

    public void deliveryComplete(IMqttDeliveryToken token) {
        System.out.println("deliveryComplete---------" + token.isComplete());
    }

    public void messageArrived(String topic, MqttMessage message) throws Exception {
        String msg = YT.toUtf8(message.toString());
        if (topic.equals("NB_DEV_UP_DATA")) {
            if (msg.startsWith("{")) {
                MTnb_dev_data bean = JsonHelper.toBean(msg, MTnb_dev_data.class);
                String imei = bean.getIMEI();
                if (Common.hasValue(bean.getIMEI())) {
                    try {
                        service.saveNbDevData(msg);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                //建立连接信息
                if (bean.getMESSAGEID().equals("00")) {
                    OpenCommand mqCommand = MQCommon.subscribeInfo.get(imei);
                    if (mqCommand != null) {
                        if (mqCommand.getSTATUS() == 1) {
                            setError(301, "没有下达81命令，无法继续开锁 " + imei);
                        } else {
                            mqCommand.setSTATUS(1);//开锁中
                            downCommand(bean.getIMEI(), bean.getMESSAGETIME());
                        }
                    } else {
                        setError(310, "00没有找到设备信息，无法发生命令 " + imei);
                    }

                }
                if (bean.getMESSAGEID().equals("81")) {

                    OpenCommand mqCommand = MQCommon.subscribeInfo.get(imei);
                    if (mqCommand != null) {
                        if (bean.getERRCODE() > 0) {
                            mqCommand.setSTATUS(2);
                            downCommand(bean.getIMEI(), bean.getMESSAGETIME());
                        } else if (mqCommand.STATUS == 1) {
                            MTnb_pub_user_data data = new MTnb_pub_user_data();
                            data.setIMEI(bean.getIMEI());
                            data.setERRCODE(0);
                            data.setMESSAGEID(bean.getMESSAGEID());
                            data.setWARN_ID(0);
                            Server server = new Server();
                            server.publish("PUB_" + mqCommand.getUSER_ID() + "_DATA", JsonHelper.toJson(data), 1);
                            MQCommon.subscribeInfo.remove(imei);

                        } else {
                            setError(312, "81-00没有00直接开锁成功-错误， " + imei);
                        }
                    } else {
                        setError(310, "81没有找到设备信息，无法发生命令 " + imei);
                    }
                }

            }

        } else if (topic.equals("IOT_HUB_ERR_INFO")) {
            MTnb_error bean = JsonHelper.toBean(msg, MTnb_error.class);
            //等于零正确，需要删除队列
            if (bean.getERRORCODE() == 0) {

            } else {
                service.insertError(bean);
            }
        }
    }

    public void downCommand(String imei, Date msgTime) {
        MTnb_dev_req mreq = service.getLastReq(imei);
        if (mreq != null) {
            boolean res = Common.getFiveMinutesDiff(mreq.getMESSAGETIME(), msgTime);
            if (res) {
                MTnb_dev_down_command downCommandData = new MTnb_dev_down_command();
                downCommandData.setIMEI(imei);
                downCommandData.setMESSAGEID("81");
                downCommandData.setCOMMAND("open:" + mreq.getDOOR());
                try {
                    Server server = new Server();
                    server.publish("NB_DEV_DOWN_DATA", JsonHelper.toJson(downCommandData), 1);
                    service.saveDownCommand(downCommandData);
                } catch (MqttException e) {
                    e.printStackTrace();
                }
            } else {
                setError(250, "超过时间，无法打开门 " + imei);
                MQCommon.subscribeInfo.remove(imei);
            }
        } else {
            setError(200, "没有请求，无法打开门 " + imei);
        }
    }

    private void setError(int code, String msg) {
        MTnb_error error = new MTnb_error();
        error.setERRORCODE(code);
        error.setMESSAGETIME(new Date());
        error.setMSG(msg);
        service.insertError(error);
    }

}

